From 667fa3e264c6d3c68c5fcf1072d92ad1e6b62d46 Mon Sep 17 00:00:00 2001 From: Ori Livneh Date: Wed, 1 Apr 2015 16:16:09 -0700 Subject: [PATCH] Make WebRequest objects time-aware * Deprecate $wgRequestTime in favor of $_SERVER['REQUEST_TIME_FLOAT'], which is more accurate. Because $_SERVER['REQUEST_TIME_FLOAT'] is only set for PHP 5.4+, set it to microtime( true ) in WebStart.php for back-compatibility. * Add a 'requestTime' property to WebRequest objects, set to $_SERVER['REQUEST_TIME_FLOAT'] for WebRequest or the instance creation time for FauxRequest instances. * Use that to provide WebRequest::getElapsedTime(), which gets the time since the request was initiated. * In wfLogProfilingData(), get the user and request objects from the context object rather than from global scope. Opportunistic clean-up: move the magic quotes check to WebStart.php and make the error message more helpful. Change-Id: I7e07e22eaf16b5141b80ad9f843285c542a127b7 --- includes/GlobalFunctions.php | 15 ++++++--------- includes/WebRequest.php | 28 +++++++++++++++++++++++++--- includes/WebStart.php | 20 +++++++++++++++++++- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index bc3a46b394..70473ca77b 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -1237,10 +1237,10 @@ function wfErrorLog( $text, $file, array $context = array() ) { * @todo document */ function wfLogProfilingData() { - global $wgRequestTime, $wgDebugLogGroups, $wgDebugRawPage; - global $wgProfileLimit, $wgUser, $wgRequest; + global $wgDebugLogGroups, $wgDebugRawPage, $wgProfileLimit; $context = RequestContext::getMain(); + $request = $context->getRequest(); $config = $context->getConfig(); if ( $config->has( 'StatsdServer' ) ) { $statsdServer = explode( ':', $config->get( 'StatsdServer' ) ); @@ -1260,7 +1260,7 @@ function wfLogProfilingData() { // Get total page request time and only show pages that longer than // $wgProfileLimit time (default is 0) - $elapsed = microtime( true ) - $wgRequestTime; + $elapsed = $request->getElapsedTime(); if ( $elapsed <= $wgProfileLimit ) { return; } @@ -1296,16 +1296,13 @@ function wfLogProfilingData() { // Don't load $wgUser at this late stage just for statistics purposes // @todo FIXME: We can detect some anons even if it is not loaded. // See User::getId() - if ( $wgUser->isItemLoaded( 'id' ) && $wgUser->isAnon() ) { - $ctx['anon'] = true; - } else { - $ctx['anon'] = false; - } + $user = $context->getUser(); + $ctx['anon'] = $user->isItemLoaded( 'id' ) && $user->isAnon(); // Command line script uses a FauxRequest object which does not have // any knowledge about an URL and throw an exception instead. try { - $ctx['url'] = urldecode( $wgRequest->getRequestURL() ); + $ctx['url'] = urldecode( $request->getRequestURL() ); } catch ( Exception $ignored ) { // no-op } diff --git a/includes/WebRequest.php b/includes/WebRequest.php index df88b355fa..054eceb97c 100644 --- a/includes/WebRequest.php +++ b/includes/WebRequest.php @@ -50,6 +50,12 @@ class WebRequest { */ private $ip; + /** + * The timestamp of the start of the request, with microsecond precision. + * @var float + */ + protected $requestTime; + /** * Cached URL protocol * @var string @@ -57,9 +63,8 @@ class WebRequest { protected $protocol; public function __construct() { - if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) { - throw new MWException( "MediaWiki does not function when magic quotes are enabled." ); - } + $this->requestTime = isset( $_SERVER['REQUEST_TIME_FLOAT'] ) + ? $_SERVER['REQUEST_TIME_FLOAT'] : microtime( true ); // POST overrides GET data // We don't use $_REQUEST here to avoid interference from cookies... @@ -216,6 +221,17 @@ class WebRequest { } } + /** + * Get the number of seconds to have elapsed since request start, + * in fractional seconds, with microsecond resolution. + * + * @return float + * @since 1.25 + */ + public function getElapsedTime() { + return microtime( true ) - $this->requestTime; + } + /** * Get the current URL protocol (http or https) * @return string @@ -1274,6 +1290,8 @@ class FauxRequest extends WebRequest { public function __construct( $data = array(), $wasPosted = false, $session = null, $protocol = 'http' ) { + $this->requestTime = microtime( true ); + if ( is_array( $data ) ) { $this->data = $data; } else { @@ -1497,4 +1515,8 @@ class DerivativeRequest extends FauxRequest { public function getProtocol() { return $this->base->getProtocol(); } + + public function getElapsedTime() { + return $this->base->getElapsedTime(); + } } diff --git a/includes/WebStart.php b/includes/WebStart.php index da4bc87920..9c71f3e1cb 100644 --- a/includes/WebStart.php +++ b/includes/WebStart.php @@ -34,12 +34,30 @@ if ( ini_get( 'register_globals' ) ) { . 'for help on how to disable it.' ); } +if ( function_exists( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) { + die( 'MediaWiki does not function when magic quotes are enabled. ' + . 'Please see the PHP Manual ' + . 'for help on how to disable magic quotes.' ); +} + + # bug 15461: Make IE8 turn off content sniffing. Everybody else should ignore this # We're adding it here so that it's *always* set, even for alternate entry # points and when $wgOut gets disabled or overridden. header( 'X-Content-Type-Options: nosniff' ); -$wgRequestTime = microtime( true ); +# Approximate $_SERVER['REQUEST_TIME_FLOAT'] for PHP<5.4 +if ( !isset( $_SERVER['REQUEST_TIME_FLOAT'] ) ) { + $_SERVER['REQUEST_TIME_FLOAT'] = microtime( true ); +} + +/** + * @var float Request start time as fractional seconds since epoch + * @deprecated since 1.25; use $_SERVER['REQUEST_TIME_FLOAT'] or + * WebRequest::getElapsedTime() instead. + */ +$wgRequestTime = $_SERVER['REQUEST_TIME_FLOAT']; + unset( $IP ); # Valid web server entry point, enable includes. -- 2.20.1